package com.efast.cafe.portal.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.efast.cafe.framework.constant.SecurityConstant;
import com.efast.cafe.portal.security.filter.MyUsernamePasswordAuthenticationFilter;
import com.efast.cafe.portal.security.handler.MyLoginFailureHandler;
import com.efast.cafe.portal.security.handler.MyLoginSuccessHandler;
import com.efast.cafe.portal.security.handler.MyLogoutSuccessHandler;
import com.efast.cafe.portal.security.service.MyAuthenticationManager;

/**
 * 
    * @ClassName: WebSecurityConfig
    * @Description: spring security 安全登录配置
    * @author xuanming.feng
    * @date 2018年8月3日
    *
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

	
	/**
	 * 实现spring security 中的UserDetailsService接口
	 * UserDetailsService接口用于返回用户相关数据。
	 * 它有loadUserByUsername()方法，根据username查询用户实体，可以实现该接口覆盖该方法，
	 * 实现自定义获取用户过程。该接口实现类被DaoAuthenticationProvider 类使用，用于认证过程中载入用户信息。
	 */
	@Autowired
	MyAuthenticationManager userDetailsService;
	
	/**
	 * 用户登录成功返回json的handler
	 */
	@Autowired
	MyLoginSuccessHandler loginSuccessHandler;
	
	/**
	 * 用户登录失败返回json的handler
	 */
	@Autowired
	MyLoginFailureHandler loginFailureHandler;
	
	/**
	 * 用户安全退出返回json的handler
	 */
	@Autowired
	MyLogoutSuccessHandler logoutSuccessHandler;
	
	 
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	http.headers().frameOptions().disable();
    	
    	http.addFilterAt(usernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
		http.formLogin().loginProcessingUrl(SecurityConstant.LOGIN_PATH).and().logout().logoutUrl(SecurityConstant.LOGOUT_PATH).
		logoutSuccessHandler(logoutSuccessHandler);
		
		http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true);
		/*此段为任何访问都必须授权  已设置通用filter校验权限供各模块使用
		http.authorizeRequests().anyRequest().fullyAuthenticated();*/
		//http.sessionManagement().maximumSessions(1);
		
		http.csrf().disable();
		
//		http
//        .csrf()
//            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
//		
//		http.csrf().ignoringAntMatchers(SecurityConstant.LOGIN_PATH,
//				SecurityConstant.LOGOUT_PATH,"/openHTTP/*","/favicon.ico","/openWS/*","/openSocket/*");
    }
    
    /**
     * 
        * @Title: usernamePasswordAuthenticationFilter
        * @Description: 自定义用户登录filter 
        * @param @return
        * @param @throws Exception    参数
        * @return UsernamePasswordAuthenticationFilter    返回类型
        * @throws
     */
    private UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter()throws Exception{
    	UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new MyUsernamePasswordAuthenticationFilter();
    	usernamePasswordAuthenticationFilter.setPostOnly(true);
        usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
        //只有post请求才拦截
        usernamePasswordAuthenticationFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(SecurityConstant.LOGIN_PATH, "POST"));
        usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(loginSuccessHandler);
        usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(loginFailureHandler);
        //并发控制,同账号只能登录一次
        //usernamePasswordAuthenticationFilter.setSessionAuthenticationStrategy(new MyConcurrentSessionControlAuthenticationStrategy(sessionRegistry));
        return usernamePasswordAuthenticationFilter;
    }
    
    /**
     * 设置认证接口实现和密码校验方式
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
    
    public static void main(String[] args) {
		System.out.println(new BCryptPasswordEncoder().encode("111111"));
	}
}
